<script lang='ts'>
import { ElNotification } from 'element-plus'
import { defineComponent, onMounted, PropType, reactive, ref, watch, nextTick } from 'vue'
import { ModelFormCallback, ModelFormExpose, ModelFormStatus } from './interface'
import { ServiceApi } from '/@/api/_base'
export default defineComponent({
    name: 'JxtechModelForm'
})
</script>
<script lang='ts' setup>
const emit = defineEmits<{
    (e: 'update:formStatus', val: ModelFormStatus): void//表单状态
    (e: 'add-success', data: any, res: any): void//保存成功回调
    (e: 'update-success', data: any, res: any): void//更新成功回调
    (e: 'save-success', data: any, res: any): void//保存更新都回调
}>()
const props = defineProps({
    formData: {
        type: Object,
        default: () => { }
    },
    primaryKey: {//主键 如果数据对象里面的主键为空 则认定为新增模式 反之为修改模式
        type: String,
        required: true
    },
    serviceApi: {
        type: Object as PropType<ServiceApi>,
        required: true
    },
    labelWidth: {
        type: [String, Number],
        default: '120px'
    },
    /**是否关联别的bean查询 后台有配置 */
    refCols: {
        type: String,
        default: "default",
    },
    //新增表单状态双向绑定功能
    formStatus: {
        type: String as PropType<ModelFormStatus>,
        default: null,
    },//表单状态
    newBeanFunction: Function,//new-bean方法
    idFunction: Function,//主键id查询方法
    saveInsertFunction: Function,//新增保存方法
    saveUpdateFunction: Function,//修改保存方法
    //回调对象 newBeanCallback:Function idCallback:Function preAdd preUpdate preSave 默认可以没有
    callback: Object as PropType<ModelFormCallback>
})

const JxtechModelFormRef = ref()

const JxtechModelFormState = reactive({
    /**这个是获取传入的对象实体中主键是否有值 如果有值则为编辑 如果无值则为新增 */
    primaryKeyValue: props.formData[props.primaryKey],
    /**表单状态 */
    formStatus: props.formStatus,
    /**表单loading */
    loading: true,
    loadingText: '拼命加载中',
    /**清理校验 */
    clearValidate: () => {
        JxtechModelFormRef.value.clearValidate()
    },
    /**初始化表单 */
    initForm: () => {
        JxtechModelFormState.primaryKeyValue = props.formData[props.primaryKey];
        //初始化表单状态
        if (JxtechModelFormState.primaryKeyValue) {
            JxtechModelFormState.formStatus = "edit"
        } else {
            JxtechModelFormState.formStatus = "add"
        }
        JxtechModelFormState.initFormData()
    },
    initFormData: () => {
        //新增的情况下
        if (JxtechModelFormState.formStatus == "add") {
            //如果为新增 执行newBean方法
            let _callback = (data: any) => {
                for (let key in data) {
                    //2021/12/16 当返回值为null时也需要覆盖掉之前的值 zhu_liangyu
                    props.formData[key] = data[key]
                }
                //清理null值赋值 导致的检验问题
                nextTick(() => JxtechModelFormState.clearValidate())
                if (props.callback?.afterNewBean) props.callback.afterNewBean(data)
            }
            if (props.newBeanFunction) {
                props.newBeanFunction().then((res: any) => _callback(res.data)).finally(() => JxtechModelFormState.closeLoading())
            } else {
                props.serviceApi.add().then((res: any) => _callback(res.data)).finally(() => JxtechModelFormState.closeLoading())
            }
        }
        //修改情况下
        if (JxtechModelFormState.formStatus == 'edit') {
            let _callback = ((data: any) => {
                for (let key in data) {
                    //2021/12/16 当返回值为null时也需要覆盖掉之前的值 zhu_liangyu
                    props.formData[key] = data[key]
                }
                if (props.callback?.afterId) props.callback.afterId(data)
            })
            if (props.idFunction) {
                props.idFunction(JxtechModelFormState.primaryKeyValue).then((res: any) => _callback(res.data)).finally(() => JxtechModelFormState.closeLoading())
            } else {
                props.serviceApi.queryById(JxtechModelFormState.primaryKeyValue, { refCols: props.refCols }).then((res: any) => _callback(res.data)).finally(() => JxtechModelFormState.closeLoading())
            }
        }
    },
    /**关闭laoding */
    closeLoading: () => {
        JxtechModelFormState.loading = false
    },
    /**保存新增数据方法*/
    saveInsertFormData: () => {
        //新增保存前
        if (props.callback?.preAdd) {
            let flag = props.callback.preAdd(props.formData)
            if (flag === false) return false
        }
        //新增修改保存前都执行
        if (props.callback?.preSave) {
            let flag = props.callback.preSave(props.formData)
            if (flag === false) return false
        }
        let _callback = (data: any, res: any) => {
            ElNotification({
                message: '数据新建成功',
                type: 'success',
            })
            emit("add-success", data, res)
            emit("save-success", data, res)
        }
        if (props.saveInsertFunction) {
            props.saveInsertFunction(props.formData).then((res: any) => _callback(res.data, res))
        } else {
            props.serviceApi.saveInsert(props.formData).then((res: any) => _callback(res.data, res))
        }
    },
    /**保存修改数据方法*/
    saveUpdateFormData() {
        if (props.callback?.preUpdate) {
            const flag = props.callback.preUpdate(props.formData)
            if (flag === false) return false
        }
        if (props.callback?.preSave) {
            const flag = props.callback.preSave(props.formData)
            if (flag === false) return false
        }
        let _callback = (data: any, res: any) => {
            ElNotification({
                message: '数据编辑成功',
                type: 'success',
            })
            //这里把值重新赋值一下
            for (let key in data) {
                if (data[key]) props.formData[key] = data[key]
            }
            emit("update-success", data, res)
            emit("save-success", data, res)
        }
        //为了兼容老的系统 我们需要内置一个__pk__的属性 以供saveUpdate时使用
        props.formData['__pk__'] = JxtechModelFormState.primaryKeyValue
        if (props.saveUpdateFunction) {
            props.saveUpdateFunction(props.formData).then((res: any) => _callback(res.data, res))
        } else {
            setTimeout(() => { }, 3000)
            props.serviceApi.saveUpdate(props.formData).then((res: any) => _callback(res.data, res))
        }
    },
    /**重置表单 */
    reloadForm() {
        console.log("重置表单", JxtechModelFormState.primaryKeyValue, props.formData);

        JxtechModelFormState.initForm();
    }
})

//监听主键的key值 如果他修改了以后 我们修改JxtechModelFormState。primaryKeyValue的值
// watch(() => props.formData[props.primaryKey], val => {
//     console.log("我是主键的值 我修改了", val)
//     JxtechModelFormState.primaryKeyValue = val;
// })

//双向绑定formStatus
watch(() => props.formStatus, val => {
    JxtechModelFormState.formStatus = val
})
watch(() => JxtechModelFormState.formStatus, val => {
    emit("update:formStatus", val)
})

/**
 * 提供
 */
const modelFormExpose: ModelFormExpose = {
    save: () => {
        JxtechModelFormRef.value.validate((valid: boolean) => {
            if (!valid) {
                console.log('error submit!!')
                return false
            }
            JxtechModelFormState.formStatus == "add" ? JxtechModelFormState.saveInsertFormData() : JxtechModelFormState.saveUpdateFormData()
        })
    },
    getModelFormStatus: () => JxtechModelFormState.formStatus,
    reloadForm: () => JxtechModelFormState.reloadForm(),
    validateField: (key: string) => {
        console.log(key)
        JxtechModelFormRef.value.validateField(key)
    }
}

//对外暴露接口
defineExpose({
    ...modelFormExpose
})

onMounted(() => {
    JxtechModelFormState.initForm()
})
</script>
<template>
    <el-form
        ref="JxtechModelFormRef"
        :model="formData"
        :label-width="labelWidth"
        v-loading="JxtechModelFormState.loading"
        :element-loading-text="JxtechModelFormState.loadingText"
    >
        <slot></slot>
    </el-form>
</template>